package com.sense.kukoo.common.mvvm.vm
import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.sense.kukoo.common.mvvm.model.BaseMvvmModel
import com.sense.kukoo.common.utils.ApplicationContext
import com.sense.kukoo.lib_logger.LoggerManager
import kotlinx.coroutines.*

/**
 * @Author Lionszhang
 * @Date 2021/2/25 9:46
 * @Name BaseViewModel.java
 * @Instruction MVVM架构VM层基类
 *
 */
abstract class BaseViewModel : ViewModel(), IVModel {
    private val TAG = "BaseViewModel"

    /**
     * 吐司提示等消息LiveData
     */
    var mHintInfoLiveData: MutableLiveData<String>
    protected var mCurrentMvvmModel: BaseMvvmModel? = null
    val mShowNetworkError: MutableLiveData<Boolean> = MutableLiveData()

    /**
     * 只提供与VIEW层交互的不需要数据的LIVEDAT,View层根据传值做不同操作，跳转
     * 如果需要交互带实体数据需要重新创建LIVEDATA
     */
    var mNavLiveDate: MutableLiveData<Int>

    protected fun sendHintMessage(stringId: Int) {
        mHintInfoLiveData.postValue(getString(stringId))
    }
    protected fun sendHintMessage(str:String) {
        mHintInfoLiveData.postValue(str)
    }

    private fun getString(stringId: Int): String {

        return ApplicationContext.instance().resources?.getString(stringId).toString()
    }

    abstract override fun createModel(): BaseMvvmModel?

    /**
     * @Author Lionszhang
     * @Date 2021/3/4 11:09
     * @Param action   参数常量在子类定义
     * @Instruction 只提供与VIEW层交互的不需要数据的LIVEDAT,View层根据传值做不同操作，跳转
     * 如果需要交互带实体数据需要重新创建LIVEDATA
     */
    override fun toView(action: Int) {
        Log.e("BaseViewMode", "toView>>action=$action")
        mNavLiveDate.postValue(action)
    }

    /**
     * @Author Lionszhang
     * @Date 2021/2/25 9:33
     * @Instruction 子类ViewModel需要重写该方法释放资源
     */
    override fun onCleared() {
        super.onCleared()
        mCurrentMvvmModel?.onModelCleared()
    }

    /**
     * @Description 通用请求方法
     * @Author Lionszhang
     * @Date 2021/11/12
     */
    fun <T> request(
        onError: (error: Throwable) -> Unit = {
            it.printStackTrace()
            LoggerManager.e(TAG, "error==============" + it.cause)
            LoggerManager.e(TAG, "error==============" + it.message)
            //mShowNetworkError.postValue(true)
            toView(ACTION_HIDE_DIALOG)
        }, // 不需要处理Error可以不传
        execute: suspend CoroutineScope.() -> T
    ) {
        viewModelScope.launch(errorHandler { onError.invoke(it) }) {
            withContext(Dispatchers.IO,execute)
            /*try {
                execute()
            } catch (e: Exception) {
                e.printStackTrace()
                LoggerManager.e(TAG, "execute_cause==============" + e.cause)
                LoggerManager.e(TAG, "execute_message===================" + e.message)
                onError(e)
            }*/
        }
    }

    private fun errorHandler(onError: (error: Throwable) -> Unit): CoroutineExceptionHandler {
        return CoroutineExceptionHandler { _, throwable ->
            onError.invoke(throwable)
        }
    }

    companion object {
        /**弹窗显示常量 */
        var ACTION_SHOW_DIALOG = 100

        /**弹窗隐藏常量 */
        var ACTION_HIDE_DIALOG = 101

        /**
         * 加载数据失败
         */
        val LOAD_ERROR_RETRY = 1001
        /**
         * 加载数据成功
         */
        val LOAD_SUCCESS = 1002

    }

    init {
        createModel()
        mHintInfoLiveData = MutableLiveData()
        mNavLiveDate = MutableLiveData()
    }
}